package com.hzncc.flowable_diboot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.diboot.core.binding.QueryBuilder;
import com.diboot.core.entity.Dictionary;
import com.diboot.core.holder.ThreadLocalHolder;
import com.diboot.core.service.DictionaryService;
import com.diboot.core.util.BeanUtils;
import com.diboot.core.util.S;
import com.diboot.core.util.SqlExecutor;
import com.diboot.core.vo.LabelValue;
import com.diboot.iam.dto.IamUserSearchDTO;
import com.diboot.iam.entity.IamOrg;
import com.diboot.iam.entity.IamPosition;
import com.diboot.iam.entity.IamUser;
import com.diboot.iam.entity.IamUserPosition;
import com.diboot.iam.service.IamOrgService;
import com.diboot.iam.service.IamPositionService;
import com.diboot.iam.service.IamUserPositionService;
import com.diboot.iam.service.IamUserService;
import com.diboot.tenant.entity.IamTenant;
import com.diboot.tenant.service.IamTenantService;
import lombok.RequiredArgsConstructor;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class CommonService {

    private final IamPositionService iamPositionService;

    private final IamUserPositionService iamUserPositionService;

    private final IamOrgService iamOrgService;

    private final IamUserService iamUserService;

    private final IamTenantService iamTenantService;

    private final DictionaryService dictionaryService;

    /**
     * 获取下属
     *
     * @return
     * @author 陈广煜
     * @date 2024/6/6
     */
    public List<String> findSubEmp(IamUser user) {
        List<Map<String, String>> positions = getPositions(user);
        List<String> uids = new ArrayList<>();
        for (Map<String, String> position : positions) {
            List<String> ids = new ArrayList<>();
            String highestDataPermission = position.get("dataPermission");
            String orgId = position.get("orgId");
            if (Objects.equals(highestDataPermission, "DEPT")) {
                ids = getDeptEmp(orgId);
            }
            if (Objects.equals(highestDataPermission, "DEPT_AND_SUB")) {
                ids = getDeptAndSubEmp(orgId);
            }
            if (Objects.equals(highestDataPermission, "SELF_AND_SUB")) {
                ids = getSubEmp(orgId);
            }
            if (!ids.isEmpty()) {
                uids.addAll(ids);
            }
        }
        // 排除自身
        return uids.stream().filter(e -> !Objects.equals(e, user.getId())).distinct().collect(Collectors.toList());
    }

    /**
     * 获取下属
     *
     * @param orgId 部门id
     * @return
     * @author 陈广煜
     * @date 2024/6/21
     */
    private List<String> getSubEmp(String orgId) {
        JdbcTemplate jt = SqlExecutor.getJdbcTemplate();
        String sql = "select u.id as id,u.realname,dip.data_permission_type as permission " +
                "from dbt_iam_user u " +
                "left join dbt_iam_user_position diup on u.id = diup.user_id " +
                "left join dbt_iam_position dip on diup.position_id = dip.id " +
                "where u.is_deleted = 0 and diup.is_deleted = 0 and dip.is_deleted = 0 and data_permission_type = 'SELF' and diup.org_id = '" + orgId + "' and u.org_id = '" + orgId + "'";
        List<Map<String, String>> query = jt.query(sql, (rs, rowNum) -> {
            Map<String, String> map = new HashMap<>();
            map.put("id", rs.getString("id"));
            map.put("permission", rs.getString("permission"));
            return map;
        });
        return query.stream().map(e -> e.get("id")).collect(Collectors.toList());
    }

    /**
     * 获取用户在各个任职部门的权限
     *
     * @param user
     * @return
     * @author 陈广煜
     * @date 2024/5/31
     */
    private List<Map<String, String>> getPositions(IamUser user) {
        List<IamPosition> positionsByUser = iamPositionService.getPositionsByUser(user.getUserType(), user.getId());
        List<IamUserPosition> userPositionListByUser = iamUserPositionService.getUserPositionListByUser(user.getUserType(), user.getId());
        List<Map<String, String>> res = new ArrayList<>();
        for (IamUserPosition iamPosition : userPositionListByUser) {
            Map<String, String> map = new HashMap<>();
            IamPosition pos = positionsByUser.stream().filter(e -> e.getId().equals(iamPosition.getPositionId())).findFirst().orElse(new IamPosition());
            map.put("dataPermission", pos.getDataPermissionType());
            map.put("orgId", iamPosition.getOrgId());
            res.add(map);
        }
        return res;
    }

    /**
     * 获取部门员工id
     *
     * @param orgId
     * @return
     * @author 陈广煜
     * @date 2024/5/31
     */
    private List<String> getDeptEmp(String orgId) {

        List<IamUser> users = iamUserService.getEntityList(QueryBuilder.toQueryWrapper(new IamUserSearchDTO().setOrgId(orgId)));
        return BeanUtils.collectToList(users, IamUser::getId);
    }

    /**
     * 获取部门及下级部门员工id
     *
     * @param orgId
     * @return
     * @author 陈广煜
     * @date 2024/5/31
     */
    public List<String> getDeptAndSubEmp(String orgId) {
        List<String> childOrgIds = iamOrgService.getChildOrgIds(orgId);
        if (childOrgIds == null || childOrgIds.size() == 0) {
            childOrgIds = new ArrayList<>();
        }
        childOrgIds.add(orgId);
        QueryWrapper<IamUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("org_id", childOrgIds);
        List<IamUser> entityList = iamUserService.getEntityList(queryWrapper);
        return BeanUtils.collectToList(entityList, IamUser::getId);
    }

    /**
     * 获取部门及下级部门员工id
     *
     * @param orgId
     * @return
     * @author 陈广煜
     * @date 2024/5/31
     */
    public List<String> getDeptAndSubEmpNum(String orgId) {
        List<String> childOrgIds = iamOrgService.getChildOrgIds(orgId);
        if (childOrgIds == null || childOrgIds.size() == 0) {
            childOrgIds = new ArrayList<>();
        }
        childOrgIds.add(orgId);
        QueryWrapper<IamUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("org_id", childOrgIds);
        List<IamUser> entityList = iamUserService.getEntityList(queryWrapper);
        return BeanUtils.collectToList(entityList, IamUser::getUserNum);
    }

    /**
     * 获取租户
     *
     * @param userNum
     * @return
     * @author 陈广煜
     * @date 2024-08-02
     */
    public List<Map<String,String>> getTenants(String userNum) {
        String sql = """
                select dit.code,dit.name,dit.org_id as salesOrg from \
                 dbt_iam_tenant dit \
                 left join dbt_iam_user diu on dit.id = diu.tenant_id \
                 left join dbt_iam_account dia on dia.user_id = diu.id \
                 where dia.auth_account = ? and diu.is_deleted = 0 and dit.is_deleted = 0
                """;
        JdbcTemplate jdbcTemplate = SqlExecutor.getJdbcTemplate();
        List<Map<String,String>> result = new ArrayList<>();
        jdbcTemplate.query(sql, new String[]{userNum}, new int[]{1}, res -> {
            Map<String,String> labelValue = Map.of("label",res.getString("name"),"value", res.getString("code"),"salesOrg", Optional.ofNullable(res.getString("salesOrg")).orElse(""));
            result.add(labelValue);
        });
        return result;
    }


    /**
     * 获取办事处id
     *
     * @param userId 用户id
     * @return
     * @author 陈广煜
     * @date 2024-08-02
     */
    public String getOffice(String userId) {
        // 获取用户部门
        IamUser user = iamUserService.getEntity(userId);
        String orgId = user.getOrgId();
        IamOrg org = iamOrgService.getEntity(orgId);
        // 如果是办事处直接返回id
        if (org.getIsOffice() == 1) {
            return org.getId();
        }
        // 获取上级部门
        String parentIdsPath = org.getParentIdsPath();
        if (S.isBlank(parentIdsPath)) {
            return null;
        }
        // 查询办事处
        List<String> parents = S.splitToList(parentIdsPath);
        QueryWrapper<IamOrg> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().select(IamOrg::getId).eq(IamOrg::getIsOffice, 1).in(IamOrg::getId, parents);
        IamOrg office = iamOrgService.getSingleEntity(queryWrapper);
        if (office != null) {
            return office.getId();
        } else {
            return null;
        }
    }


    /**
     * 获取办事处
     *
     * @param tenantId 租户id
     * @return
     * @author 陈广煜
     * @date 2024-08-07
     */
    public List<LabelValue> getOfficeLabelValueList(String tenantId) {
        QueryWrapper<IamOrg> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().select(IamOrg::getId, IamOrg::getName).eq(IamOrg::getIsOffice, 1).eq(IamOrg::getTenantId, tenantId);
        ThreadLocalHolder.setIgnoreInterceptor();
        return iamOrgService.getLabelValueList(queryWrapper);
    }

    /**
     * 获取上级领导
     *
     * @param empId 员工id
     * @return
     * @author 陈广煜
     * @date 2024-08-22
     */
    public List<String> getLeaderIds(String empId) throws Exception {
        IamUser user = iamUserService.getEntity(empId);
        List<Map<String, String>> positions = getPositions(user);
        List<String> res = new ArrayList<>();
        for (Map<String, String> position : positions) {
            List<String> orgLeader = getOrgLeader(position.get("orgId"), position.get("dataPermission"));
            if (orgLeader != null && orgLeader.size() > 0) {
                res.addAll(orgLeader);
            }
        }
        return res;
    }


    /**
     * 获取部门内部领导
     *
     * @param orgId
     * @param dataPermissionType
     * @return
     * @author 陈广煜
     * @date 2024-08-23
     */
    public List<String> getOrgLeader(String orgId, String dataPermissionType) throws Exception {
        String leaderPermission = switch (dataPermissionType) {
            case "SELF" -> "SELF_AND_SUB";
            case "SELF_AND_SUB" -> "DEPT";
            case "DEPT", "DEPT_AND_SUB" -> "DEPT_AND_SUB";
            default -> "";
        };
        String sql = """
                select \
                diu.id \
                from \
                dbt_iam_user diu \
                left join dbt_iam_user_position diup on \
                diu.id = diup.user_id \
                left join dbt_iam_position dip on \
                dip.id = diup.position_id \
                where \
                diu.is_deleted = 0 \
                and dip.is_deleted = 0 \
                and diup.is_deleted = 0 \
                and diup.org_id = ? \
                and dip.data_permission_type = ?
                """;
        List<Map<String, Object>> maps = SqlExecutor.executeQuery(sql, new String[]{orgId, leaderPermission});
        return maps.stream().map(map -> map.get("id").toString()).collect(Collectors.toList());
    }

    /**
     * 判断租户是否是跨租户的
     *
     * @param tenantId 租户ID，用于唯一标识一个租户
     * @return 返回一个Boolean值，表示租户是否是跨租户的
     */
    public Boolean isCrossTenant(String tenantId) {
        // 获取指定ID的租户实体
        IamTenant tenant = iamTenantService.getEntity(tenantId);
        // 返回租户是否为跨租户，其中1表示是，0表示否
        return tenant.getCrossTenant() == 1;
    }

    /**
     * 根据字典类型和描述获取字典项列表
     *
     * @param dictType 字典类型，用于筛选符合条件的字典项
     * @param desc 字典描述，与类型一起用于精确筛选字典项
     * @return 返回一个LabelValue对象的列表，每个对象包含字典项的相关信息
     */
    public List<LabelValue> getDictionaryByTypeAndDes(String dictType,String desc) {
        // 创建一个Lambda查询链包装器，用于构建对Dictionary表的查询条件
        LambdaQueryChainWrapper<Dictionary> query = dictionaryService.lambdaQuery();

        // 选择需要查询的字段，包括类型、描述、项值、项名称和扩展字段
        query.select(Dictionary::getType,Dictionary::getDescription, Dictionary::getItemValue,Dictionary::getItemName,Dictionary::getExtension)
                // 添加等于条件，筛选出类型等于dictType的记录
                .eq(Dictionary::getType, dictType)
                // 添加等于条件，筛选出描述等于desc的记录
                .eq(Dictionary::getDescription, desc);

        // 执行查询并获取符合条件的字典项列表
        List<Dictionary> entityList = dictionaryService.getEntityList(query);

        // 将查询到的字典项实体列表转换为LabelValue对象列表，并返回
        return entityList.stream().map(Dictionary::toLabelValue).toList();
    }
}
